//
//  ConeRender.m
//  MyOpenGLESLearn_iOS
//
//  Created by Gaomingyang on 2021/4/14.
//

#import "ConeRender.h"
#import "ShaderProgram.h"


#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kConeVertexShaderString = SHADER_STRING
(
 attribute vec3 vPosition;//顶点位置
 uniform mat4 vMatrix; //总变换矩阵
 varying vec4 vColor;
 void main(){
        gl_Position = vMatrix * vec4(vPosition,1);
        if(vPosition.z!=0.0){
            vColor = vec4(0.0,0.0,0.0,1.0);
        }else{
            vColor = vec4(0.9,0.9,0.9,1.0);
        }
    }
 );
#else

#endif

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kConeFragmentShaderString = SHADER_STRING
(
 precision mediump float;
 varying vec4 vColor;
 void main(){
//     //给此片元着色值
    gl_FragColor = vColor;
//    gl_FragColor = vec4(1.0,0.0,0.0,1.0);
 }
 );
#else

#endif


@interface ConeRender()<GLKViewDelegate>
{
    // Render
    GLuint  _program;
    GLKMatrix4  _projectionMatrix;//投影矩阵
    GLKMatrix4  _viewMatrix;//相机位置
    GLKMatrix4  _MVPMatrix;//计算变换矩阵 4
}
@property (strong, nonatomic) ShaderProgram* shaderProcessor;
@property (strong, nonatomic) EAGLContext* context;
@property (strong, nonatomic) GLKView* glkView;
@property (assign,nonatomic)  int vSize;

@end
struct AttributeHandles
{
    GLint   vPosition;
};
struct UniformHandles
{
    GLuint  uProjectionMatrix;
    GLuint  uMVPMatrix;
};
@implementation ConeRender
{
    struct AttributeHandles _attributes;
    struct UniformHandles   _uniforms;

}
- (instancetype)initWithGLKView:(GLKView *)glkView{
    self = [super init];
    if (self) {
        [self commonInitWithGLKView:glkView];
    }
    return self;
}
-(void)commonInitWithGLKView:(GLKView *)glkView{
    [self initOpenglESWithGLKView:glkView];
}
-(void)initOpenglESWithGLKView:(GLKView *)glkView{
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
    // Setup View
    self.glkView = glkView;
    self.glkView.delegate = self;
    self.glkView.context = self.context;
    self.glkView.opaque = YES;
    self.glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    self.glkView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
    
    // Initialize Class Objects
    self.shaderProcessor = [[ShaderProgram alloc] init];
    [self resetupOpenGLES];
}
- (void)resetupOpenGLES
{
    [EAGLContext setCurrentContext:self.context];
    // Enable depth test
    glEnable(GL_DEPTH_TEST);
    CGRect screen = [self.glkView bounds];
    float aspectRatio = fabs(screen.size.width / screen.size.height);
    // Projection Matrix
    _projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0), aspectRatio, 3, 20);
    /**
     float eyeX, float eyeY, float eyeZ,
     float centerX, float centerY, float centerZ,
     float upX, float upY, float upZ
     */
    _viewMatrix = GLKMatrix4MakeLookAt(1, -10, -4, 0, 0, 0, 0, 1, 0);
    _MVPMatrix = GLKMatrix4Multiply(_projectionMatrix, _viewMatrix);
    // Create the GLSL program
    _program = [self.shaderProcessor BuildProgram:[kConeVertexShaderString cStringUsingEncoding:NSUTF8StringEncoding] with:[kConeFragmentShaderString cStringUsingEncoding:NSUTF8StringEncoding]];

    // end create program
    glUseProgram(_program);
    
    // Extract the attribute handles
    _attributes.vPosition = glGetAttribLocation(_program, "vPosition");
    
    _uniforms.uMVPMatrix = glGetUniformLocation(_program, "vMatrix");

}
- (void)setDisplay{
    [self.glkView display];
}
# pragma mark - GLKView Delegate
- (void)update:(id)sender {
    [self.glkView display];
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // Clear Buffers
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // Enable Attributes
    glEnableVertexAttribArray(_attributes.vPosition);
    
    glUniformMatrix4fv(_uniforms.uMVPMatrix, 1, false, _MVPMatrix.m);
    
        
    glVertexAttribPointer(_attributes.vPosition, 3, GL_FLOAT, GL_FALSE, 0,[self createConePos]);


    glDrawArrays(GL_TRIANGLE_FAN, 0, ((GLsizei)self.vSize));
    
    // Disable Attributes
    glDisableVertexAttribArray(_attributes.vPosition);
}

# pragma mark - GLKViewController Delegate
- (void)glkViewControllerUpdate:(GLKViewController *)controller
{
}

-(float *)createConePos{
     int n = 360;//切割分数
    float height = 2.0f;//圆锥高度
    float radius = 1.0f;//圆锥底部半径
    
    NSMutableArray<NSNumber *> *data = [NSMutableArray new];
    //设置圆心坐标
    [data addObject:[NSNumber numberWithFloat:0.0f]];
    [data addObject:[NSNumber numberWithFloat:0.0f]];
    [data addObject:[NSNumber numberWithFloat:height]];
    
    float angDegSpan=360.f/n;
    for(float i= 0;i<360+angDegSpan;i+=angDegSpan){
        float x = radius*sin(i*M_PI/180.f);
        float y = radius*cos(i*M_PI/180.f);
        
        [data addObject:[NSNumber numberWithFloat:x]];
        [data addObject:[NSNumber numberWithFloat:y]];
        [data addObject:[NSNumber numberWithFloat:0]];
    }
    float * result = malloc(sizeof(float)*(data.count));
            for(int i=0;i<data.count;i++){
                NSNumber *tmpF = data[i];
                result[i] = tmpF.floatValue;
            }
    self.vSize = (int)data.count/3;
    return result;
}

@end
